package net.sf.jOpinionPoll.controller.questionario;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import net.sf.jOpinionPoll.controller.Controller;
import net.sf.jOpinionPoll.entity.Alternativa;
import net.sf.jOpinionPoll.entity.QuestaoAlternativa;
import net.sf.jOpinionPoll.entity.Questionario;
import net.sf.jOpinionPoll.facade.QuestionarioFacade;
import net.sf.jOpinionPoll.miscellaneous.JOPUtil;

import org.apache.log4j.Logger;

public class QuestaoAlternativaController extends Controller {
	private static final long serialVersionUID = 6293526607543294482L;

	private static final Logger m_Logger = Logger.getLogger(QuestaoAlternativaController.class);
    
	private QuestionarioFacade m_QuestionarioFacade;
	
	private Enum<Outcome> m_Outcome;
	
	private Questionario m_Questionario;
	private Alternativa m_Alternativa;
	private QuestaoAlternativa m_QuestaoAlternativa;
	private String m_DescricaoAlternativa;
    
    private DataModel m_AlternativaDM;
    private AlternativaComparator m_AlternativaComparator;
    
    private boolean m_AtualizaLista;

    public QuestaoAlternativaController() {
		m_AlternativaDM = new ListDataModel();
		m_AlternativaComparator = new AlternativaComparator();
		
		atualizaLista();
	}
    
    public void atualizaLista() {
		m_AtualizaLista = true;
	}
    
    @PostConstruct
    @SuppressWarnings("all")
    private void inicializar() {
    	inicializaQuestionario();
    	inicializaQuestao();
    }
    
    private void inicializaQuestionario() {
		String strId = JOPUtil.requestParam("questionarioId");
		int qId;
		
		if (strId == null) {
			throw new NullPointerException("Identificacao do questionario nao encontrada");
		}
		
		qId = Integer.parseInt(strId);
		
		if (qId > 0) {
			m_Questionario = getQuestionarioFacade().findByPk(qId);
		}
		else {
			throw new NullPointerException("Identificacao do questionario invalida: " + qId);
		}
    }
    
    private void inicializaQuestao() {
		String strId = JOPUtil.requestParam("questaoId");
		int qId;
		
		if (strId == null) {
			throw new NullPointerException("Identificacao da questao nao encontrada");
		}
		
		qId = Integer.parseInt(strId);
		
		if (qId > 0) {
			m_QuestaoAlternativa = (QuestaoAlternativa)getQuestionarioFacade().findQuestaoByPk(qId);
		}
		else {
			m_QuestaoAlternativa = (QuestaoAlternativa)createBean("entityQuestaoAlternativa");
		}
    }
	
    /* Facades */
    public QuestionarioFacade getQuestionarioFacade() {
        return m_QuestionarioFacade;
    }
    
    public void setQuestionarioFacade(QuestionarioFacade questionarioFacade) {
        m_QuestionarioFacade = questionarioFacade;
    }
	
	/* Outros */
	public DataModel getListaAlternativas() {
		if (m_AtualizaLista) {
			m_AlternativaDM.setWrappedData(new ArrayList<Alternativa>(getQuestaoAlternativa().getAlternativas()));
			
			m_AtualizaLista = false;
		}
    	
        m_Logger.info("Entidades listadas");
        
        return m_AlternativaDM;
	}
	
	public Questionario getQuestionario() {
		return m_Questionario;
	}
	
	public void setQuestionario(Questionario questionario) {
		m_Questionario = questionario;
	}
    
	public Alternativa getAlternativa() {
		return m_Alternativa;
	}

	public void setAlternativa(Alternativa alternativa) {
		m_Alternativa = alternativa;
	}
	
	public QuestaoAlternativa getQuestaoAlternativa() {
		return m_QuestaoAlternativa;
	}
	
    private Alternativa getSelectedAlternativa() {
        return (Alternativa) m_AlternativaDM.getRowData();
    }
	
	public String getDescricaoAlternativa() {
		return m_DescricaoAlternativa;
	}
	
	public void setDescricaoAlternativa(String descricao) {
		m_DescricaoAlternativa = descricao;
	}
	
	public boolean getIsEditando() {
		return (getAlternativa() != null);
	}
    
	/* Listeners */
    public void novaAlternativaListener(ActionEvent evt) {
		m_Logger.info("Nova alternativa...");
		
    	setDescricaoAlternativa(null);		
		setAlternativa(null);
    }
    
	public void adicionarAlternativaListener(ActionEvent evt) {
		m_Logger.info("Adicionando alternativa...");
		
		Alternativa alt = (Alternativa)createBean("entityAlternativa");
		alt.setDescricao(getDescricaoAlternativa());
		getQuestaoAlternativa().getAlternativas().add(alt);
		atualizaLista();
		
		novaAlternativaListener(evt);
	}
	
	public void atualizarAlternativaListener(ActionEvent evt) {
		m_Logger.info("Atualizando alternativa...");

		getAlternativa().setDescricao(getDescricaoAlternativa());
		atualizaLista();
		
		novaAlternativaListener(evt);
	}
	
	@SuppressWarnings("unchecked")
	public void orderListByDescricaoListener(ActionEvent evt) {
		m_Logger.info("Ordenar por descricao...");
		
		List<Alternativa> alternativas = (List<Alternativa>)m_AlternativaDM.getWrappedData();
    	
    	m_AlternativaComparator.setCampo(AlternativaComparator.Campo.DESCRICAO);
		Collections.sort(alternativas, m_AlternativaComparator);
	}
	
	public void editarAlternativaListener(ActionEvent evt) {
		m_Logger.info("Editando alternativa...");

		setDescricaoAlternativa(getSelectedAlternativa().getDescricao());
		setAlternativa(getSelectedAlternativa());
	}
	
	public void apagarListener(ActionEvent evt) {
		m_Logger.info("Removendo entidade id " + getSelectedAlternativa().getId());
		
		getQuestaoAlternativa().getAlternativas().remove(getSelectedAlternativa());
		
		atualizaLista();
		
		novaAlternativaListener(evt);
		
        m_Logger.info("Entidade id " + getSelectedAlternativa().getId() + " removida com sucesso!");
	}
	
	public void salvarListener(ActionEvent evt) {
		if (getQuestaoAlternativa().getId() == 0) {
            m_Logger.info("Adicionando questao " + getQuestaoAlternativa().getDescricao());
            
            getQuestaoAlternativa().setData(Calendar.getInstance().getTime());

            Questionario quest = getQuestionarioFacade().findByPk(getQuestionario().getId());
            quest.getQuestoes().add(getQuestaoAlternativa());
            getQuestionarioFacade().set(quest);
            setQuestionario(quest);
            
            m_Logger.info("Questionario " + getQuestionario().getNome() + " adicionado!");
            
            m_Outcome = Outcome.ADDED;
        }
        else {
            m_Logger.info("Editando questao " + getQuestionario().getId());

			boolean encontrado = false;
			QuestaoAlternativa questao = (QuestaoAlternativa)getQuestionarioFacade().findQuestaoByPk(getQuestaoAlternativa().getId());
			Set<Alternativa> alternativas = questao.getAlternativas();
			List<Alternativa> alternativasRemover = new ArrayList<Alternativa>();
			
			for (Alternativa a1 : alternativas) {
				for(Alternativa a2 : getQuestaoAlternativa().getAlternativas()) {
					if (a1.getId() == a2.getId()) {
						encontrado = true;
						break;
					}
				}
				
				if (!encontrado) {
					alternativasRemover.add(a1);
				}
				
				encontrado = false;
			}
			
			for (Alternativa a : alternativasRemover) {
				alternativas.remove(a);
			}
			
			for (Alternativa a : alternativasRemover) {
				getQuestionarioFacade().removeAlternativa(a);
			}
			
			getQuestionarioFacade().setQuestao(getQuestaoAlternativa());
            
            m_Logger.info("Questionario " + getQuestionario().getId() + " editado!");
			
			m_Outcome = Outcome.UPDATED;
        }
	}
	
	/* Actions */
	public Enum<Outcome> salvarAction() {
		return m_Outcome;
	}
}